package cn.com.miao.lynx.plugin.mail.service.impl;

import cn.com.miao.lynx.common.core.excpetion.LynxException;
import cn.com.miao.lynx.plugin.mail.enums.ContentType;
import cn.com.miao.lynx.plugin.mail.model.MailRequest;
import cn.com.miao.lynx.plugin.mail.model.MailResponse;
import cn.com.miao.lynx.plugin.mail.service.MailService;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dm.model.v20151123.SingleSendMailRequest;
import com.aliyuncs.dm.model.v20151123.SingleSendMailResponse;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * AliYunMailService
 *
 * @title: AliYunMailService
 * @description:
 * @author: dengmiao
 * @create: 2020-01-10 14:23
 **/
@Slf4j
@Builder
@AllArgsConstructor
public class AliYunMailService implements MailService {

    /**
     * Mail Address Join Split
     */
    static final String JOIN_SPLIT = ",";
    /**
     * Acs Client Support Instance
     */
    private IAcsClient client;
    /**
     * The mail address configured in the management console.
     */
    private String accountName;
    /**
     * Use the reply address configured in the administrative console (status must be validated).
     */
    private boolean replyToAddress;
    /**
     * Random accounts range from 0 to 1:0 and addresses from 1.
     */
    private int addressType;
    /**
     * From alias
     */
    private String defaultFromAlias;
    /**
     * tag name
     */
    private String defaultTagName;

    @Override
    public MailResponse send(MailRequest apiBootMailRequest) throws LynxException {
        try {
            // check param
            checkParam(apiBootMailRequest);

            // send mail with single
            SingleSendMailRequest request = new SingleSendMailRequest();
            request.setAccountName(accountName);
            request.setFromAlias(StringUtils.isEmpty(apiBootMailRequest.getFormAlias()) ? defaultFromAlias : apiBootMailRequest.getFormAlias());
            request.setAddressType(addressType);
            // tag name
            String tagName = StringUtils.isEmpty(apiBootMailRequest.getTagName()) ? defaultTagName : apiBootMailRequest.getTagName();
            if (!StringUtils.isEmpty(tagName)) {
                request.setTagName(tagName);
            }
            request.setReplyToAddress(replyToAddress);
            request.setToAddress(String.join(JOIN_SPLIT, apiBootMailRequest.getToAddress()));
            request.setSubject(apiBootMailRequest.getSubject());
            switchBody(request, apiBootMailRequest.getContent(), apiBootMailRequest.getContentType());

            // execute send mail
            SingleSendMailResponse response = client.getAcsResponse(request);

            return MailResponse.builder().success(!StringUtils.isEmpty(response.getRequestId())).build();
        } catch (Exception e) {
            throw new LynxException(e.getMessage(), e);
        }
    }

    /**
     * check param
     *
     * @param request ApiBoot Mail Request
     * @throws LynxException ApiBoot Exception
     */
    private void checkParam(MailRequest request) throws LynxException {
        // mail content
        if (StringUtils.isEmpty(request.getContent())) {
            throw new LynxException("Mail Request Param：[contentType] is required.");
        }
        // to address
        else if (StringUtils.isEmpty(request.getToAddress())) {
            throw new LynxException("Mail Request Param：[toAddress] is required.");
        }
        // subject
        else if (StringUtils.isEmpty(request.getSubject())) {
            throw new LynxException("Mail Request Param：[subject] is required.");
        }
    }

    /**
     * switch mail body
     * if contentType is null, default use text
     *
     * @param request     single send mail request
     * @param contentType content type
     */
    private void switchBody(SingleSendMailRequest request, String content, ContentType contentType) {
        if (ObjectUtils.isEmpty(contentType)) {
            request.setTextBody(content);
        } else {
            switch (contentType) {
                case HTML:
                    request.setHtmlBody(content);
                    break;
                case TEXT:
                    request.setTextBody(content);
                    break;
            }
        }
    }
}
